package com.bestcem.xm.award.service.impl;

import com.bestcem.xm.award.controller.param.point.CheckSmsCodeParam;
import com.bestcem.xm.award.controller.param.point.SendSmsCodeParam;
import com.bestcem.xm.award.dao.AwardAwardDao;
import com.bestcem.xm.award.dao.AwardRequestDao;
import com.bestcem.xm.award.entity.pojo.AwardAwardDO;
import com.bestcem.xm.award.entity.pojo.AwardRequestDO;
import com.bestcem.xm.award.enums.AwardRequestStatusEnum;
import com.bestcem.xm.award.enums.AwardStatusEnum;
import com.bestcem.xm.award.service.AwardSmsService;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.componet.redis.service.RedisService;
import com.bestcem.xm.componet.sms.SmsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.bestcem.xm.award.constant.Constants.AWARD_SMS_CODE_TEMPLATE;
import static com.bestcem.xm.award.constant.Constants.AWARD_SMS_CODE_TEMPLATE_10MIN;
import static com.bestcem.xm.award.constant.RedisKeyConstant.*;

/**
 * @author xa.zhang <xa.zhang@idiaoyan.com>
 * @version v1.0
 * @date 2021/8/23 10:05
 * @desc 奖励通用短信验证码发送
 */
@Slf4j
@Service
public class AwardSmsServiceImpl implements AwardSmsService {

    /**
     * 默认是true 发短信
     */
    @Value("${app.award.sms:true}")
    private boolean isSms;

    @Resource
    private AwardAwardDao awardAwardDao;
    //@Resource
    //private SmsGrpcService smsGrpcService;

    @Resource
    private SmsService smsService;

    @Resource
    private AwardRequestDao requestDao;
    @Resource
    private RedisService redisService;

    /**
     * 获取验证码
     *
     * @param param 参数
     * @return 结果
     */
    /*@Override
    public ServiceResult getSmsAuthCode(SendSmsCodeParam param) {

        ServiceResult<AwardAwardDO> checkParamResult = checkParamRight(param.getAwardId(), param.getRequestId());
        if (!checkParamResult.isSuccess()) {
            return checkParamResult;
        }
        AwardAwardDO award = checkParamResult.getData();

        // 短信验证码key
        String smsCodeKey = SMS_AUTH_CODE_PREFIX + param.getAwardId() + ":" + param.getRequestId() + ":" + param.getPhone();
        // 请求频率验证
        String frequencyKey = String.format(SMS_FREQUENCY_KEY, smsCodeKey);
        long value = redisService.incr(frequencyKey, 1);
        if (value == 1) {
            redisService.expire(frequencyKey, SMS_FREQUENCY_TIMEOUT, TimeUnit.SECONDS);
        } else if (value > 1) {
            return ServiceResult.fail("请求过于频繁");
        }

        // 生成短信验证码
        String smsCodeValue = String.valueOf((int) ((Math.random() * 9 + 1) * 1000));

        String orgId = award.getOrgId();
        String name = award.getName();
        String projectId = award.getProjectId();
        String smsContent = String.format(AWARD_SMS_CODE_TEMPLATE, smsCodeValue, AWARD_SMS_CODE_TEMPLATE_10MIN);
        if (isSms) {
            // 发送短信
            SendSmsRequest.Builder request = SendSmsRequest.newBuilder();
            request.setOrgId(orgId).setProjectId(projectId).setName(name).setPhone(param.getPhone())
                    .setContent(smsContent).setTypeValue(SmsRecordTypeEnum.SmsRecordType.DRAW_VALUE);
            try {
                SendSmsResponse smsResponse = smsGrpcService.sendSms(request.build());
                if (Code.OK_VALUE == smsResponse.getStatus().getCodeValue()) {
                    if (log.isInfoEnabled()) {
                        log.info("手机号{}, 发送短信验证码{}", param.getPhone(), smsCodeValue);
                    }
                } else {
                    log.error("手机号{}, 短信验证码发送失败: {}", param.getPhone(), smsResponse.getStatus().getMessage());
                    return ServiceResult.fail("短信验证码发送失败");
                }
            } catch (Exception e) {
                log.error("手机号{}, 短信服务调用错误:", param.getPhone(), e);
                return ServiceResult.fail("短信服务调用失败");
            }
        }
        // 保存验证码
        redisService.set(smsCodeKey, smsCodeValue, SMS_AUTH_CODE_TIMEOUT, TimeUnit.SECONDS);
        return ServiceResult.success();
    }*/
    @Override
    public ServiceResult getSmsAuthCode(SendSmsCodeParam param) {

        ServiceResult<AwardAwardDO> checkParamResult = checkParamRight(param.getAwardId(), param.getRequestId());
        if (!checkParamResult.isSuccess()) {
            return checkParamResult;
        }
        AwardAwardDO award = checkParamResult.getData();

        // 短信验证码key
        String smsCodeKey = SMS_AUTH_CODE_PREFIX + param.getAwardId() + ":" + param.getRequestId() + ":" + param.getPhone();
        // 请求频率验证
        String frequencyKey = String.format(SMS_FREQUENCY_KEY, smsCodeKey);
        long value = redisService.incr(frequencyKey, 1);
        if (value == 1) {
            redisService.expire(frequencyKey, SMS_FREQUENCY_TIMEOUT, TimeUnit.SECONDS);
        } else if (value > 1) {
            return ServiceResult.fail("请求过于频繁");
        }

        // 生成短信验证码
        String smsCodeValue = String.valueOf((int) ((Math.random() * 9 + 1) * 1000));

        String orgId = award.getOrgId();
        String name = award.getName();
        String projectId = award.getProjectId();
        String smsContent = String.format(AWARD_SMS_CODE_TEMPLATE, smsCodeValue, AWARD_SMS_CODE_TEMPLATE_10MIN);
        if (isSms) {
            // 发送短信
            try {
                Map<String, Object> map = smsService.sendSms(param.getPhone(), smsContent, null);
                if (!ObjectUtils.isEmpty(map)) {
                    if (log.isInfoEnabled()) {
                        log.info("手机号{}, 发送短信验证码{}", param.getPhone(), smsCodeValue);
                    }
                } else {
                    log.error("手机号{}, 短信验证码发送失败: {}", param.getPhone(), map);
                    return ServiceResult.fail("短信验证码发送失败");
                }
            } catch (Exception e) {
                log.error("手机号{}, 短信服务调用错误:", param.getPhone(), e);
                return ServiceResult.fail("短信服务调用失败");
            }
        }
        // 保存验证码
        redisService.set(smsCodeKey, smsCodeValue, SMS_AUTH_CODE_TIMEOUT, TimeUnit.SECONDS);
        return ServiceResult.success();
    }

    /**
     * 校验验证码
     *
     * @param param 参数
     * @return 结果
     */
    @Override
    public ServiceResult verifySmsAuthCode(CheckSmsCodeParam param) {
        ServiceResult<AwardAwardDO> checkParamResult = checkParamRight(param.getAwardId(), param.getRequestId());
        if (!checkParamResult.isSuccess()) {
            return checkParamResult;
        }

        String smsCodeKey = SMS_AUTH_CODE_PREFIX + param.getAwardId() + ":" + param.getRequestId() + ":" + param.getPhone();
        if (isSms) {
            String smsCode = redisService.getString(smsCodeKey);
            // 验证码校验
            if (StringUtils.isBlank(smsCode) || !StringUtils.equals(smsCode, param.getCode())) {
                return ServiceResult.fail("验证码错误");
            }
        }
        //保存校验结果
        redisService.set(smsCodeKey + ":result", "true", SMS_AUTH_CODE_RESULT_TIMEOUT, TimeUnit.SECONDS);

        return ServiceResult.success();
    }

    /**
     * 检查参数是否合理完整
     *
     * @param awardId   奖励id
     * @param requestId 请求id
     * @return
     */
    @Override
    public ServiceResult checkParamRight(String awardId, String requestId) {
        AwardAwardDO award = awardAwardDao.findById(awardId);
        if (Objects.isNull(award)) {
            return ServiceResult.fail("奖励不存在");
        }
        if (award.getStatus() == null || award.getStatus().intValue() != AwardStatusEnum.ACTIVE.getIndex()) {
            return ServiceResult.fail("奖励未激活");
        }
        //参数完整性校验
        AwardRequestDO awardRequestDO = requestDao.findById(requestId);
        if (awardRequestDO == null || (!award.getId().equals(awardRequestDO.getAwardId())) ||
                awardRequestDO.getStatus() == null) {
            return ServiceResult.fail("参数不合理");
        }
        if (awardRequestDO.getStatus().intValue() != AwardRequestStatusEnum.PASS.getIndex()) {
            return ServiceResult.fail("无法重复领取");
        }
        return ServiceResult.success(award);
    }

}
